package com.ljy.my_study.leetcode.有效的数独;

import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;

/**
 * @author lijunying
 * @date 2021/9/13 15:06
 */
public class TestMain {

//    请你判断一个 9x9 的数独是否有效。只需要 根据以下规则 ，验证已经填入的数字是否有效即可。
//
//    数字 1-9 在每一行只能出现一次。
//    数字 1-9 在每一列只能出现一次。
//    数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。（请参考示例图）
//    数独部分空格内已填入了数字，空白格用 '.' 表示。
//
//    注意：
//
//    一个有效的数独（部分已被填充）不一定是可解的。
//    只需要根据以上规则，验证已经填入的数字是否有效即可。
//             
//
//    示例 1：
//
//
//    输入：board =
//            [['5','3','.','.','7','.','.','.','.']
//            ,['6','.','.','1','9','5','.','.','.']
//            ,['.','9','8','.','.','.','.','6','.']
//            ,['8','.','.','.','6','.','.','.','3']
//            ,['4','.','.','8','.','3','.','.','1']
//            ,['7','.','.','.','2','.','.','.','6']
//            ,['.','6','.','.','.','.','2','8','.']
//            ,['.','.','.','4','1','9','.','.','5']
//            ,['.','.','.','.','8','.','.','7','9']]
//    输出：true
//    示例 2：
//
//    输入：board =
//            [['8','3','.','.','7','.','.','.','.']
//            ,['6','.','.','1','9','5','.','.','.']
//            ,['.','9','8','.','.','.','.','6','.']
//            ,['8','.','.','.','6','.','.','.','3']
//            ,['4','.','.','8','.','3','.','.','1']
//            ,['7','.','.','.','2','.','.','.','6']
//            ,['.','6','.','.','.','.','2','8','.']
//            ,['.','.','.','4','1','9','.','.','5']
//            ,['.','.','.','.','8','.','.','7','9']]
//    输出：false
//    解释：除了第一行的第一个数字从 5 改为 8 以外，空格内其他数字均与 示例1 相同。 但由于位于左上角的 3x3 宫内有两个 8 存在, 因此这个数独是无效的。
//             
//
//    提示：
//
//    board.length == 9
//    board[i].length == 9
//    board[i][j] 是一位数字或者 '.'
//
//    来源：力扣（LeetCode）
//    链接：https://leetcode-cn.com/problems/valid-sudoku
//    著作权归领扣网络所有。商业转载请联系官方授权，非商业转载请注明出处。

    public static void main(String[] args) {
        char[][] board= {{'5','3','.','.','7','.','.','.','.'}
                        ,{'6','.','.','1','9','5','.','.','.'}
                        ,{'.','9','8','.','.','.','.','6','.'}
                        ,{'8','.','.','.','6','.','.','.','3'}
                        ,{'4','.','.','8','.','3','.','.','1'}
                        ,{'7','.','.','.','2','.','.','.','6'}
                        ,{'.','6','.','.','.','.','2','8','.'}
                        ,{'.','.','.','4','1','9','.','.','5'}
                        ,{'.','.','.','.','8','.','.','7','9'}};
        System.out.println(new TestMain().isValidSudoku(board));
    }

    public boolean isValidSudoku(char[][] board) {
        Map<Integer,Set<Integer>> xMap=new HashMap<>();
        Map<Integer,Set<Integer>> yMap=new HashMap<>();
        Map<Integer,Set<Integer>> innerMap=new HashMap<>();

        int len=board.length;
        for(int i=0;i<len;i++){
            for(int j=0;j<len;j++){
                char c=board[i][j];
                if(c=='.'){
                    continue;
                }
                int val=c-'0';
                if(!checkAndAdd(xMap,i,val)){
                    return false;
                }
                if(!checkAndAdd(yMap,j,val)){
                    return false;
                }
                int index=(i/3)*3+(j/3);
                if(!checkAndAdd(innerMap,index,val)){
                    return false;
                }
            }
        }
        return true;
    }

    private boolean checkAndAdd(Map<Integer, Set<Integer>> map, int i, int val){
        Set<Integer> set= map.getOrDefault(i,new LinkedHashSet<>());
        if(set.contains(val)){
            return false;
        }
        set.add(val);
        map.put(i,set);
        return true;
    }
}
